package com.bims.jreport.service.impl;


import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.bims.jreport.cache.CustomCache;
import com.bims.jreport.dao.JooqDaoUtil;
import com.bims.jreport.document.DocTemplate;
import com.bims.jreport.jooq.db.tables.records.TTemplateFileRecord;
import com.bims.jreport.jooq.db.tables.records.TTemplateRecord;
import com.bims.jreport.mapper.ReportMapper;
import com.bims.jreport.pdf.builder.BuilderContext;
import com.bims.jreport.pdf.builder.MultiPdfBuilder;
import com.bims.jreport.pojo.bo.ReportTemplateBo;
import com.bims.jreport.service.JreportService;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.pdf.PdfDocument;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

import static com.bims.jreport.jooq.db.tables.TTemplate.T_TEMPLATE;
import static com.bims.jreport.jooq.db.tables.TTemplateFile.T_TEMPLATE_FILE;

/**
 * @author wangrenjie
 */
@Service
public class JreportServiceImpl implements JreportService {

    @Autowired
    @Qualifier(CustomCache.FONT_CACHE)
    private CustomCache<String, PdfFont> customCache;


    @Autowired
    private JooqDaoUtil daoUtil;

    @Autowired
    private ReportMapper reportMapper;

    /**
     * 保存
     *
     * @param reportTemplateBo Bo
     * @return 是否成功
     */
    @Override
    public boolean save(ReportTemplateBo reportTemplateBo) {
        //生成文件
        PdfDocument documentTemplate = this.getDocumentTemplate(reportTemplateBo.getTemplate());
        ByteArrayOutputStream outputStream = (ByteArrayOutputStream) documentTemplate.getWriter().getOutputStream();
        String baseFile = Base64.encode(outputStream.toByteArray());
        IoUtil.close(outputStream);
        IoUtil.close(documentTemplate);
        //保存模板
        TTemplateRecord templateRecord = reportMapper.bo2Rec(reportTemplateBo);
        templateRecord.setCreateTime(LocalDateTime.now());
        Integer ver = daoUtil.getDsl().select(DSL.max(T_TEMPLATE.VER)).from(T_TEMPLATE).where(T_TEMPLATE.FORM_ID.eq(reportTemplateBo.getFormId())).limit(1).fetchOneInto(Integer.class);
        //设置版本
        ver = null != ver ? ver + 1 : 1;
        templateRecord.setVer(ver);
        templateRecord.setId(UUID.randomUUID());
        int num = daoUtil.getDao(T_TEMPLATE).insertDirectly(templateRecord);
        //保存文件
        TTemplateFileRecord fileRecord = new TTemplateFileRecord(UUID.randomUUID(), templateRecord.getId(), baseFile);
        int fileNum = daoUtil.getDao(T_TEMPLATE_FILE).insertDirectly(fileRecord);
        return num > 0 && fileNum > 0;
    }

    /**
     * 删除
     *
     * @param templateId 模板ID
     * @return 是否成功
     */
    @Override
    public boolean delete(UUID templateId) {
        //删除模板
        int num = daoUtil.getDao(T_TEMPLATE).deleteById(templateId);
        //删除文件
        int execute = daoUtil.getDsl().deleteFrom(T_TEMPLATE_FILE).where(T_TEMPLATE_FILE.TEMPLATE_ID.eq(templateId)).execute();
        return num > 0 && execute > 0;
    }

    /**
     * 删除所有
     *
     * @return 是否成功
     */
    @Override
    public boolean deleteAll(UUID formId) {
        //删除模板
        List<UUID> templateIds = daoUtil.getDsl().select(T_TEMPLATE.ID).from(T_TEMPLATE).where(T_TEMPLATE.FORM_ID.eq(formId)).fetchInto(UUID.class);
        int num = daoUtil.getDao(T_TEMPLATE).deleteById(templateIds.toArray());
        //删除文件
        int execute = daoUtil.getDsl().deleteFrom(T_TEMPLATE_FILE).where(T_TEMPLATE_FILE.TEMPLATE_ID.in(templateIds)).execute();
        return num > 0 && execute > 0;
    }

    /**
     * 获取最新版
     *
     * @param formId 表单ID
     * @return Bo
     */
    @Override
    public ReportTemplateBo getLast(UUID formId) {
        //查找最大的版本
        TTemplateRecord templateRecord = daoUtil.getDsl().select(T_TEMPLATE.fields()).from(T_TEMPLATE).where(T_TEMPLATE.FORM_ID.eq(formId)).orderBy(T_TEMPLATE.VER.desc()).limit(1).fetchOneInto(TTemplateRecord.class);
        return reportMapper.rec2Bo(templateRecord);
    }

    /**
     * 获得所有版本
     *
     * @param formId
     * @return
     */
    @Override
    public List<ReportTemplateBo> getVers(UUID formId) {
        //获得所有版本 名称，ID
        List<TTemplateRecord> records = daoUtil.getDsl().select(T_TEMPLATE.ID, T_TEMPLATE.NAME).from(T_TEMPLATE).where(T_TEMPLATE.FORM_ID.eq(formId)).fetchInto(TTemplateRecord.class);
        return reportMapper.recs2Bos(records);
    }

    /**
     * 详情
     *
     * @param templateId 模板ID
     * @return BO
     */
    @Override
    public ReportTemplateBo get(UUID templateId) {
        TTemplateRecord record = daoUtil.getDao(T_TEMPLATE).findById(templateId);
        return reportMapper.rec2Bo(record);
    }

    /**
     * 预览
     *
     * @param template 模板JSON
     */
    @Override
    public OutputStream preview(String template) {
        PdfDocument documentTemplate = this.getDocumentTemplate(template);
        return documentTemplate.getWriter().getOutputStream();
    }

    /**
     * 获得文档模板
     *
     * @param templateJson 模板JSON
     * @return PDF文档
     */
    @Override
    public PdfDocument getDocumentTemplate(String templateJson) {
        //JSON.DEFAULT_TYPE_KEY="__t";
        DocTemplate docTemplate = JSON.parseObject(templateJson, DocTemplate.class);
        //构建上下文
        BuilderContext context = new BuilderContext(docTemplate, customCache.getAll());
        MultiPdfBuilder multiPdfBuilder = new MultiPdfBuilder(docTemplate.fetchPageSize(), docTemplate.fetchCustomOption(), context, docTemplate.fetchBody());
        return multiPdfBuilder.build();
    }

}
